// HSS.Forms.DetailModuleBase.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       DetailModuleBase.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/04/2010
// ----------------------------------------------------------------------------
namespace HSS.Forms
{
	#region Using Directives
	using System;
	using System.ComponentModel;
	using System.Windows.Forms;
	using HSS.Data;
	#endregion

	#region DetailModuleBase
	/// <summary>
	/// DetailModuleBase is a UserControl that could be used as a base class that 
	/// provides for the editing of data and shown via the <see cref="DetailModuleContainer"/>
	/// </summary>
	[ToolboxItem(false)]
	public partial class DetailModuleBase : ModuleBase
	{
		#region Events
		/// <summary>
		/// StateChanged Event
		/// </summary>
		public event EventHandler StatusChanged;
		/// <summary>
		/// Event notification if the AllowEdit Property has changed
		/// </summary>
		public event EventHandler AllowEditChanged;
		/// <summary>
		/// Event notification if the AllowCreateNew Property has changed
		/// </summary>
		public event EventHandler AllowCreateNewChanged;
		/// <summary>
		/// Event notification if the WarnOnCancel Property has changed
		/// </summary>
		public event EventHandler ShowApplyButtonChanged;

		/// <summary>
		/// Triggers the event delegate
		/// </summary>
		private void InvokeAllowEditChanged(object sender, EventArgs e)
		{
			if (null != this.AllowEditChanged)
			{
				System.Delegate[] dlgs = this.AllowEditChanged.GetInvocationList();
				if (null != dlgs)
				{
					foreach (Delegate d in dlgs)
					{
						if (null != d)
						{
							InvokeDelegate(d, new object[2] { sender, e });
						}
					}
				}
			}
		}
		/// <summary>
		/// Triggers the event delegate
		/// </summary>
		private void InvokeAllowCreateNewChanged(object sender, EventArgs e)
		{
			if (null != this.AllowCreateNewChanged)
			{
				System.Delegate[] dlgs = this.AllowCreateNewChanged.GetInvocationList();
				if (null != dlgs)
				{
					foreach (Delegate d in dlgs)
					{
						if (null != d)
						{
							InvokeDelegate(d, new object[2] { sender, e });
						}
					}
				}
			}
		}
		/// <summary>
		/// Triggers the event delegate
		/// </summary>
		private void InvokeShowApplyButtonChanged(object sender, EventArgs e)
		{
			if (null != this.ShowApplyButtonChanged)
			{
				System.Delegate[] dlgs = this.ShowApplyButtonChanged.GetInvocationList();
				if (null != dlgs)
				{
					foreach (Delegate d in dlgs)
					{
						if (null != d)
						{
							InvokeDelegate(d, new object[2] { sender, e });
						}
					}
				}
			}
		}
		#endregion

		#region Constructor
		/// <summary>
		/// ctor
		/// </summary>
		public DetailModuleBase()
		{
			InitializeComponent();
		}
		#endregion

		#region Properties

		#region Nonbrowseable
		/// <summary>
		/// Indicates if this formhas been loaded
		/// </summary>
		[Description("Indicates if this form has been loaded.")]
		[Browsable(false)]
		[DefaultValue(false)]
		public bool Loaded
		{
			get { return _loaded; }
			set { _loaded = value; }
		} bool _loaded;
		/// <summary>
		/// Indicates if this form is currently loading
		/// </summary>
		[Description("Indicates if this form is currently loading.")]
		[Browsable(false)]
		[DefaultValue(false)]
		public bool Loading
		{
			get { return _loading; }
			set { _loading = value; }
		} bool _loading;
		/// <summary>
		/// Indicates if this form is currently updating
		/// </summary>
		[Description("Indicates if this form is currently updating.")]
		[Browsable(false)]
		[DefaultValue(false)]
		public bool Updating
		{
			get { return _updating; }
			set { _updating = value; }
		} bool _updating;
		/// <summary>
		/// Contains the data for this form
		/// </summary>
		[Description("Contains the data for this form.")]
		[Browsable(false)]
		public IDataContainer DetailData
		{
			get { return _detailData; }
			set { _detailData = value; }
		} IDataContainer _detailData;
		/// <summary>
		/// The current Action of this form
		/// </summary>
		[Description("The current Action of this form.")]
		[Browsable(false)]
		public ModuleActions CurrentAction
		{
			get { return _CurrentAction; }
			set
			{
				_CurrentAction = value;
				if (null != this.StatusChanged)
					this.StatusChanged(this, EventArgs.Empty);
			}
		} ModuleActions _CurrentAction;
		/// <summary>
		/// The Primary KEY for the data currently loaded in the Module
		/// </summary>
		[Description("The Primary KEY for the data currently loaded in the Module.")]
		[Browsable(false)]
		[DefaultValue("-1")]
		public string UniqueID
		{
			get { return _uniqueID; }
			set { _uniqueID = value; }
		} string _uniqueID = "-1";
		#endregion

		#region Appearance
		/// <summary>
		/// The Borderstyle of the Container Form.
		/// </summary>
		[Description("The FormBorderStyle of the Container Form.")]
		[CategoryAttribute("Appearance")]
		[DefaultValue(FormBorderStyle.Sizable)]
		public FormBorderStyle ParentBorderStyle
		{
			get
			{
				return _parentBorderStyle;
			}
			set
			{
				_parentBorderStyle = value;
			}
		} FormBorderStyle _parentBorderStyle = FormBorderStyle.Sizable;
		#endregion

		#region Behavior
		/// <summary>
		/// Indicates if the module allows editing
		/// </summary>
		[Description("Indicates if the module allows editing.")]
		[CategoryAttribute("Behavior")]
		[DefaultValue(true)]
		public bool AllowEdit
		{
			get { return _allowEdit; }
			set
			{
				if (_allowEdit != value)
				{
					_allowEdit = value;
					InvokeAllowEditChanged(this, EventArgs.Empty);
				}
			}
		} bool _allowEdit = true;
		/// <summary>
		/// Indicates if the Module allows creating a new record
		/// </summary>
		[Description("Indicates if the Module allows creating a new record.")]
		[CategoryAttribute("Behavior")]
		[DefaultValue(false)]
		public bool AllowCreateNew
		{
			get { return _allowCreateNew; }
			set
			{
				if (_allowCreateNew != value)
				{
					_allowCreateNew = value;
					InvokeAllowCreateNewChanged(this, EventArgs.Empty);
				}
			}
		} bool _allowCreateNew;
		/// <summary>
		/// Warn user if canceling a change
		/// </summary>
		[Description("Warn user if canceling a change")]
		[Category("Behavior")]
		[DefaultValue(true)]
		public bool WarnOnCancel
		{
			get { return _warnOnCancel; }
			set { _warnOnCancel = value; }
		} bool _warnOnCancel = true;
		/// <summary>
		/// Indicates if the Dialog should close when the user cancels their changes.
		/// </summary>
		[Description("Indicates if the Dialog should close when the user cancels their changes.")]
		[Category("Behavior")]
		[DefaultValue(false)]
		public bool CloseOnCancel
		{
			get
			{
				return _closeOnCancel;
			}
			set
			{
				_closeOnCancel = value;
			}
		} bool _closeOnCancel;
		/// <summary>
		/// Indicates if the form should display the Apply Button
		/// </summary>
		[Description("Indicates if the form should display the Apply Button")]
		[CategoryAttribute("Behavior")]
		[DefaultValue(false)]
		public bool ShowApplyButton
		{
			get { return _showApplyButton; }
			set
			{
				if (_showApplyButton != value)
				{
					_showApplyButton = value;
					InvokeShowApplyButtonChanged(this, EventArgs.Empty);
				}
			}
		} bool _showApplyButton;
		/// <summary>
		/// Indicates if the Container of this Module, should raise it's Saved event
		/// </summary>
		[Description("Indicates if the Container of this Module, should raise it's Saved event")]
		[Category("Behavior")]
		[DefaultValue(true)]
		public bool RaiseSavedEvent
		{
			get { return _raiseSavedEvent; }
			set { _raiseSavedEvent = value; }
		} bool _raiseSavedEvent = true;
		#endregion

		#region Display
		/// <summary>
		/// The Title or Overview for this Module
		/// </summary>
		[Description("The Title or Overview for this Module")]
		[Category("Display")]
		[DefaultValue("")]
		public string ModuleTitle
		{
			get { return _ModuleTitle; }
			set { _ModuleTitle = value; }
		} string _ModuleTitle = string.Empty;
		/// <summary>
		/// The description or action for this Module
		/// </summary>
		[Description("The description or action for this child Module")]
		[Category("Display")]
		[DefaultValue("")]
		public string ActionDescription
		{
			get { return _actionDescription; }
			set { _actionDescription = value; }
		} string _actionDescription = string.Empty;
		/// <summary>
		/// The Text to Display on the OK Button
		/// </summary>
		[Description("The Text to Display on the OK Button")]
		[Category("Display")]
		[DefaultValue("&OK")]
		public string OKButtonText
		{
			get { return _okButtonText; }
			set { _okButtonText = value; }
		} string _okButtonText = "&OK";
		/// <summary>
		/// The Image to display for the Module
		/// </summary>
		[Description("The Image to display for the module.")]
		[CategoryAttribute("Display")]
		[DefaultValue(null)]
		public System.Drawing.Image Image
		{
			get { return _image; }
			set { _image = value; }
		} System.Drawing.Image _image = null;
		#endregion

		#region Layout
		/// <summary>
		/// Indicates whether or not to show the Header Area
		/// </summary>
		[Description("Indicates whether or not to show the Header Area.")]
		[CategoryAttribute("Layout")]
		[DefaultValue(true)]
		public bool HeaderVisible
		{
			get
			{
				return _headerVisible;
			}
			set
			{
				_headerVisible = value;
			}
		} bool _headerVisible = true;
		/// <summary>
		/// Indicates the desired height of the Header Area
		/// </summary>
		[Description("Indicates the desired height of the Header Area.")]
		[CategoryAttribute("Layout")]
		[DefaultValue(70)]
		public int HeaderHeight
		{
			get
			{
				return _headerHeight;
			}
			set
			{
				_headerHeight = value;
			}
		} int _headerHeight = 70;
		/// <summary>
		/// Specifies the initial position of the Parent Form.
		/// </summary>
		[Description("Specifies the initial position of the Parent Form.")]
		[CategoryAttribute("Layout")]
		[DefaultValue(true)]
		public FormStartPosition ParentStartPosition
		{
			get { return _parentStartPosition; }
			set { _parentStartPosition = value; }
		} FormStartPosition _parentStartPosition = FormStartPosition.CenterParent;
		#endregion

		#region Window Style
		/// <summary>
		/// The Icon to display for the Module's Parent Form
		/// </summary>
		[Description("The Icon to display for the Module's Parent Form.")]
		[CategoryAttribute("Window Style")]
		[DefaultValue(null)]
		public System.Drawing.Icon ParentIcon
		{
			get { return _parentIcon; }
			set { _parentIcon = value; }
		} System.Drawing.Icon _parentIcon = null;
		/// <summary>
		/// Should the Container Form show the Maximize Box.
		/// </summary>
		[Description("Should the Container Form show the Maximize Box.")]
		[CategoryAttribute("Window Style")]
		[DefaultValue(true)]
		public bool MaximizeBox
		{
			get { return _containerMaximize; }
			set { _containerMaximize = value; }
		} bool _containerMaximize = true;
		/// <summary>
		/// Should the Container Form show the Minimize Box.
		/// </summary>
		[Description("Should the Container Form show the Minimize Box.")]
		[CategoryAttribute("Window Style")]
		[DefaultValue(true)]
		public bool MinimizeBox
		{
			get { return _containerMinimize; }
			set { _containerMinimize = value; }
		} bool _containerMinimize = true;
		/// <summary>
		/// Should the Container Form be shown in the TaskBar.
		/// </summary>
		[Description("Should the Container Form be shown in the TaskBar.")]
		[CategoryAttribute("Window Style")]
		[DefaultValue(true)]
		public bool ShowInTaskbar
		{
			get { return _showInTaskBar; }
			set { _showInTaskBar = value; }
		} bool _showInTaskBar = true;
		#endregion

		#endregion

		#region Methods
		/// <summary>
		/// Virtual Method for the initializing a detail form
		/// </summary>
		/// <param name="Action">The action to take on this form during initialization</param>
		/// <param name="Data">The data contained on the form</param>
		/// <returns>true if the Child Control successfully initialized into the desired state; else false</returns>
		public virtual bool InitializeModule(ModuleActions Action, IDataContainer Data)
		{
			this.Loading = true;

			this.LoadLookup(true);

			this.Reset();

			switch (Action)
			{
				case ModuleActions.New:
					this.UniqueID = string.Empty;
					this.LoadData();
					break;

				case ModuleActions.Edit:
					this.UniqueID = Data.Id;
					this.DetailData = Data;
					this.LoadData();
					break;
			}

			// Remember last state
			this.CurrentAction = Action;

			// Labels
			DeactivateLabels(this.Controls);

			// Done
			this.IsDirty = false;
			this.Loaded = true;
			this.Loading = false;

			return true;
		}
		/// <summary>
		/// Virtual method for the loading data into the detail form. Is called by default from the <see cref="InitializeModule"/> method
		/// </summary>
		public virtual void LoadData() { }
		/// <summary>
		/// Virtual Method for the getting the data from the detail form
		/// </summary>
		/// <returns>IDataContainer</returns>
		public virtual IDataContainer GetData()
		{
			IDataContainer val = null;
			return val;
		}
		/// <summary>
		/// Virtual Method for saving the data on the detail form
		/// </summary>
		/// <param name="SaveAndNew">Save and set state to New</param>
		/// <returns></returns>
		public virtual bool SaveData(bool SaveAndNew)
		{
			string ErrorMessage = string.Empty;

			if (!ValidateData(ref ErrorMessage))
			{
				if (ErrorMessage.Length > 0)
					MsgBox(ErrorMessage, MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}

			// Get new values
			this.DetailData = this.GetData();

			// Store Id
			this.UniqueID = this.DetailData.Id;

			// No longer dirty
			this.IsDirty = false;

			return true;
		}
		/// <summary>
		/// Virtual Method for the reseting the detail form
		/// </summary>
		protected virtual void Reset() { }
		/// <summary>
		/// Virtual Method for the loading the lookups
		/// </summary>
		protected virtual void LoadLookup(bool preserveSelectValue) { }
		/// <summary>
		/// Set Module to a Dirty State
		/// </summary>
		protected virtual void SetDirty()
		{
			this.SetDirty(true);
		}
		/// <summary>
		/// Set Module to a Dirty State
		/// </summary>
		/// <param name="IsEditing">Indicates user has begun editing fields</param>
		protected virtual void SetDirty(bool IsEditing)
		{
			this.SetDirty(false, IsEditing, null);
		}
		/// <summary>
		/// Set Module to a Dirty State
		/// </summary>
		/// <param name="ForceDirty">Force setting Module to dirty and raise event.</param>
		/// <param name="IsEditing">Indicates user has begun editing fields</param>
		protected virtual void SetDirty(bool ForceDirty, bool IsEditing)
		{
			this.SetDirty(ForceDirty, IsEditing, null);
		}
		/// <summary>
		/// Set Module to a Dirty State
		/// </summary>
		/// <param name="ForceDirty">Force setting Module to dirty and raise event.</param>
		/// <param name="IsEditing">Indicates user has begun editing fields</param>
		/// <param name="State">State object</param>
		protected virtual void SetDirty(bool ForceDirty, bool IsEditing, object State)
		{
			if (!this.IsDirty | ForceDirty)
				this.IsDirty = true;
			InvokeDirty(this, new DirtyEventArgs(this.IsDirty, IsEditing, State));
		}
		/// <summary>
		/// Set Modules Dirty State
		/// </summary>
		/// <param name="IsDirty">Indicates if form is dirty</param>
		/// <param name="State">State object</param>
		protected virtual void SetDirty(bool IsDirty, object State)
		{
			this.IsDirty = IsDirty;
			InvokeDirty(this, new DirtyEventArgs(IsDirty, true, State));
		}
		/// <summary>
		/// Validate date before saving
		/// </summary>
		/// <returns>Boolean indicating if Data is valid</returns>
		protected virtual bool ValidateData(ref string ErrorMessage) { return true; }
		#endregion
	}
	#endregion
}